#pragma once
#include "resource.h"     
#include <atlctl.h>
#include "AddinLib_i.h"
#include "Config.h"

using namespace ATL;


// CTaskPane is the actual ActiveX control that provides the content of the CustomTaskPane
// It is responsible for creating and hosting the webbrowser, and for forwading
// events to the JS VM after the JS Application has loaded
class ATL_NO_VTABLE CTaskPane :
	public CComObjectRootEx<CComSingleThreadModel>,
	public IDispatchImpl<ITaskPaneControl, &IID_ITaskPaneControl, &LIBID_StatCloud9MsoAddin, /*wMajor =*/ 1, /*wMinor =*/ 0>,
	public IOleControlImpl<CTaskPane>,
	public IOleObjectImpl<CTaskPane>,
	public IOleInPlaceActiveObjectImpl<CTaskPane>,
	public IViewObjectExImpl<CTaskPane>,
	public IOleInPlaceObjectWindowlessImpl<CTaskPane>,
	public ISupportErrorInfo,
	public CComCoClass<CTaskPane, &CLSID_TaskPane>,
	public CComControl<CTaskPane>
{
private:
	CComPtr<IWebBrowser2> m_spBrowser;
	CComQIPtr<IAxWinHostWindow> m_spWindow;
	CComPtr<IAddin> m_pAddin;
public:
	CTaskPane()
	{
		m_bWindowOnly = TRUE;
	}

DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_INSIDEOUT |
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST
)

DECLARE_REGISTRY_RESOURCEID(IDR_TASKPANE)


BEGIN_COM_MAP(CTaskPane)
	COM_INTERFACE_ENTRY(ITaskPaneControl)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(IViewObjectEx)
	COM_INTERFACE_ENTRY(IViewObject2)
	COM_INTERFACE_ENTRY(IViewObject)
	COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
	COM_INTERFACE_ENTRY(IOleInPlaceObject)
	COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
	COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
	COM_INTERFACE_ENTRY(IOleControl)
	COM_INTERFACE_ENTRY(IOleObject)
	COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()

BEGIN_PROP_MAP(CTaskPane)
	PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
	PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
END_PROP_MAP()


BEGIN_MSG_MAP(CTaskPane)
	MESSAGE_HANDLER(WM_CREATE, OnCreate)
	CHAIN_MSG_MAP(CComControl<CTaskPane>)
	DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()

// Handler prototypes:
//  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);

// ISupportsErrorInfo
	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
	{
		static const IID* const arr[] =
		{
			&IID_ITaskPaneControl,
		};

		for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
		{
			if (InlineIsEqualGUID(*arr[i], riid))
				return S_OK;
		}
		return S_FALSE;
	}

// IViewObjectEx
	DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)

// ITaskPane
public:
	STDMETHOD(Init)(IAddin *pAddin) {
		if(m_pAddin)
			return E_FAIL; // already initialized
		if(!pAddin) 
			return E_POINTER;

		this->m_pAddin = pAddin;
		return S_OK;
	}

	STDMETHOD(get_Addin)(IAddin **ppAddin) {
		return m_pAddin->QueryInterface(ppAddin);
	}
	
	STDMETHOD(get_HTMLDocument)(IDispatch ** ppDoc) {
		return m_spBrowser->get_Document(ppDoc);
	}

	STDMETHOD(get_Visible)(VARIANT_BOOL *pBool) {
		if(!pBool)
			return E_POINTER;

		*pBool = VARIANT_FALSE;
	
		if(!m_pAddin)
			return S_OK;

		CComPtr<IDispatch> pPaneDisp;
		CComPtr<_CustomTaskPane> pPane;
		HRESULT hr = m_pAddin->get_TaskPane(&pPaneDisp);
		if(SUCCEEDED(hr)) 
			hr = pPaneDisp->QueryInterface(&pPane);
		if(SUCCEEDED(hr))
			hr = pPane->get_Visible(pBool);

		return hr;
	}

	
	STDMETHOD(put_Visible)(VARIANT_BOOL visible) {
		if(!m_pAddin)
			return S_OK;

		CComPtr<IDispatch> pPaneDisp;
		CComPtr<_CustomTaskPane> pPane;
		HRESULT hr = m_pAddin->get_TaskPane(&pPaneDisp);
		if(SUCCEEDED(hr)) 
			hr = pPaneDisp->QueryInterface(&pPane);
		if(SUCCEEDED(hr))
			hr = pPane->put_Visible(visible);

		return hr;
	}


// Window stuff
public:
	HRESULT OnDraw(ATL_DRAWINFO& di)
	{
		// Don't draw anything because the WebBrowser control will do the drawing.
		return S_OK;
	}

	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
			CAxWindow wnd(m_hWnd);

		CConfigHelper config;

		wnd.ModifyStyle(WS_HSCROLL | WS_VSCROLL, 0);
		HRESULT hr = wnd.CreateControl(L"{8856F961-340A-11D0-A96B-00C04FD705A2}");
		
		if (SUCCEEDED(hr)) {
			hr = wnd.QueryHost(&m_spWindow);
		}
		if (SUCCEEDED(hr)) {
			hr = wnd.QueryControl(IID_IWebBrowser2, (void**)&m_spBrowser);
		}
		if (SUCCEEDED(hr)) {
			CComBSTR url;
			config.GetAppUrl(&url);
			hr = m_spBrowser->Navigate(url, NULL, NULL, NULL, NULL);
		}
		if(SUCCEEDED(hr)) {
			hr = m_spWindow->SetExternalDispatch(static_cast<IDispatch*>(this));
		}

		return SUCCEEDED(hr) ? 0 : -1;
	}

	STDMETHOD(TranslateAccelerator)(LPMSG pMsg)
	{
		CComPtr<IOleInPlaceActiveObject> spIOleInPlaceActiveObject;

		HRESULT hr = m_spBrowser->QueryInterface(&spIOleInPlaceActiveObject);
		if (SUCCEEDED(hr))
			hr = spIOleInPlaceActiveObject->TranslateAccelerator(pMsg);
		if (hr != S_OK)
			hr = IOleInPlaceActiveObjectImpl<CTaskPane>::TranslateAccelerator(pMsg);

		return hr;
	}

public:
	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}
};

OBJECT_ENTRY_AUTO(__uuidof(TaskPane), CTaskPane)
